1W - Gateway API를 활용한 설정
개요
여태의 실습에서는 이스티오의 리소스인 VirtualService, Gateway 등을 활용했다.
최근 쿠버네티스에는 인그레스를 대체하는 리소스로서 Gateway API가 나왔다.
(최근이라기엔 좀 오래된 것 같기도..)
이것을 통해서도 이스티오의 서비스 메시를 관리하는 것이 가능한데, 이번 문서에서는 이것을 이용해 이전 실습을 재현해볼 것이다.
사전 지식
Gateway API
Gateway API is a family of API kinds that provide dynamic infrastructure provisioning and advanced traffic routing.[1]
게이트웨이 api는 동적인 인프라 프로비저닝과 향상된 트래픽 라우팅 기능을 제공하는 api 종류의 집합이다.
그냥 게이트웨이면 게이트웨이라 하지 싶은데, 3가지의 오브젝트가 합쳐진 콤비네이션이라 굳이 이렇게 부르는 듯하다.
인그레스를 거의 상속하는 대체제로 최근 조금씩 사람들도 인식하고 있는 것 같다.
기본으로 쿠버네티스의 api로 제공되는 것은 아니고, CRD를 설치해주어야 한다.
Gateway API vs API Gateway
처음 이름을 접할 때 조금 헷갈리는 포인트.[2]
이름으로 말장난 하는 거 아니냐! 싶지만..
api 게이트웨이는 백엔드 서비스를 노출하는 일반적인 시스템 아키텍처를 이야기한다.
물론 여기에 트래픽 라우팅, 밸런싱, 인증 인가 등의 다양한 기능을 가질 수 있다.
반면 게이트웨이 api는 쿠버네티스 네트워킹을 위해 제공되는 인터페이스이자 모델, 집합체이다.
그래서 api 게이트웨이라는 컨셉 아래 게이트웨이 api라는 프레임, 모델이 성립한다고 보면 되겠다.
이 모델을 구현하는 구현체에 따라 차이는 있겠으나 게이트웨이 api는 api 게이트웨이로서의 기능을 가진다.
기능 - 디자인 구조
게아 아키텍쳐는 아래의 디자인 원칙을 따르며 설계됐다.
- 역할 기반 - 조직적 역할을 기반으로 구성될 수 있도록 하여 운영 이슈를 줄인다.
- 인프라 제공자 - 클러스터 자원 제공자로, 여러 클러스터에 여러 테넌시를 관리한다.
- 클러스터 운영자 - 정책, 네트워크 접근, 앱 권한 등을 설정하는 관리자로, 한 클러스터의 전반을 책임진다.
- 앱 개발자 - 앱 레벨의 설정과 구성에 초점을 맞추는 개발자로, 클러스터 위에서 구동될 앱을 만든다.
- 휴대성 - 커스텀 리소스를 기반으로 정의되어 다양한 구현체를 가진다.
- 표현성 - 헤더 기반, 가중치 기반 라우팅 등 어노테이션으로만 제공한 인그레스의 기능들을 지원한다.
- 확장성 - api의 다양한 층과 결합하여 트래픽 아키텍쳐 상에 적절한 장소에 커스텀 리소스를 넣을 수 있게 한다.
나는 기능을 이렇게 두 가지 관점에서 정리하고자 한다.
- 클러스터 내의 조직 역할 기반으로 네트워크 관련 권한 및 설정 분리
- 인그레스보다 확장성 있고 유연한 트래픽 처리 기능(로드밸런싱, 헤더 조작, 인증 인가 등)
아무튼 세 그룹의 역할을 기반으로 개발이 됐기에 보다시피 3개의 오브젝트가 나오게 됐다.
종류
그래서 어떤 오브젝트들이 있는가?
게아에서는 조직에서 역할 기반 설정을 제공하고자 상호의존적인 관계를 맺는 오브젝트들을 만들었다.
이런 식으로 각 오브젝트에 권한을 부여하여 책임 영역을 확실하게 지정하는 방향으로 운영에 활용할 수 있다!
GatewayClass
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: example-class
spec:
controllerName: example.com/gateway-controller
클래스를 구현하는 컨트롤러와 설정을 통해 여러 게이트웨이를 정의하는 오브젝트.
인프라 제공자가 설정할 영역의 오브젝트라고 할 수 있다.
컨트롤러와는 1:1 관계를 맺는다.
이 친구는 클러스터 전역의 리소스로, 인그레스로 치자면 Ingress#인그레스 클래스라고 할 수 있다.
Gateway
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: example-gateway
spec:
gatewayClassName: example-class
listeners:
- name: http
protocol: HTTP
port: 80
로드 밸런싱 등의 트래픽 처리 인프라 인스턴스를 정의하는 오브젝트.
클러스터 운영자가 설정할 영역의 오브젝트라고 할 수 있다.
여기에서 어떤 트래픽들을 어떻게 처리하고 싶은지 설정한다.
가령 80으로 들어오는 http 프로토콜만 처리하고 싶다던가, 하는 설정들이 있겠다.
자신의 리스너에 첨부될 수 있는 경로를 필터링함으로써 양방향 신뢰 관계를 형성할 수 있다.
개발자가 아무 경로나 열어버리지 않도록, 운영자가 제한할 수 있다는 말이다.
네트워크 흐름으로서는 말 그대로 게이트웨이 역할을 한다.
즉, 클러스터에 들어올 ip 경로가 곧 게이트웨이가 되는 것이다.
위의 GatewayClass와는 다:1 관계를 맺는다.
즉 하나의 GatewayClass는 여러 Gateway를 가질 수 있다.
(가진다는 표현은 조금 애매한데, 여러 Gateway가 하나의 GatewayClass를 참조할 수 있다 보는 게 좋겠다.)
예시로는 클러스터 외부를 들었지만, 그냥 트래픽이 서비스로 연결될 수 있는 길로서의 역할을 하기에 당연히 내부에서도 사용될 수 있다.
그런 식으로 설정하면 완벽히 API Gateway로서 설정하는 것이라 할 수 있겠다.
기본설정과 행동은 GatewayClass에 의해 지정된다.
참고로 이 리소스를 지정하면 실제 트래픽을 담당하게 될 서비스와 워크로드가 알아서 배포된다.
이 부분은 이스티오의 gateway와 분명하게 대비되는 지점이며, 같이 생기게 될 리소스들에 대해 설정을 하는 필드도 존재한다.[3]
Route
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: example-httproute
spec:
parentRefs:
- name: example-gateway
hostnames:
- "www.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /login
backendRefs:
- name: example-svc
port: 8080
Gateway 리소스의 리스너로부터 백엔드포인트로 이어지는 구체적인 트래픽 규칙을 지정하는 오브젝트.
앱 개발자가 설정할 영역의 오브젝트라고 할 수 있다.
따지자면 이 놈이 라우팅 룰을 넣는 인그레스와 비교될 만하겠다.
여기에서의 엔드포인트는 서비스를 의미하며, 구체적으로 어떻게 연결할지에 대한 규칙을 지정한다.
위의 게이트웨이에 세부 규칙들을 지정하여 원하는 작업들을 수행한다.
프로토콜, 경로, 헤더 등 다양한 것들을 기반으로 연결할 백엔드를 지정할 수 있다.
게이트웨이와 다:다 관계를 맺는다.
즉 하나의 게이트웨이가 여러 라우트를 가질 수 있고, 하나의 라우트 역시 여러 게이트웨이에 붙여질 수 있다.
객체 지향 디자인 패턴으로 치면 커맨드 패턴 느낌이랄까?
프로토콜 별로 세부적인 라우트 종류가 있다.
- HTTPRoute
- GRPCRoute
- TLSRoute
- TCPRoute
- UDPRoute
이름만 봐도 뭔지 알만 해서 추가적으로 설명은 않겠다만, 현재 stable 단계인 것은 아직 http, grpc 뿐이다.
동작 흐름
동작 흐름을 구체적으로 따라가보자.
클라이언트의 dns 쿼리 요청은 게이트웨이의 ip 주소를 알려준다.
해당 주소로 요청이 날아가면 이 게이트웨이에 붙은 httproute 중 조건에 매칭되는 놈이 작동할 것이다.
여기에서 헤더를 제거하던, 바꾸던 경로를 바꾸던 각종 다양한 작업을 할 수 있고 이것이 최종적으로 서비스로 전달된다.
서비스 메시 설정 리소스로서의 Gateway API
먼저 분명히 할 지점이 있는 게, 기본적으로 gateway api는 인그레스를 대체하기 위해 개발됐다.
그래서 클러스터 바깥에서 들어오는 트래픽을 관리하는데 특화돼있다는 것을 유의해야 한다.
게이트웨이라는 이름에 걸맞게 클러스터 내외부를 연결하는, North-South 트래픽을 관리하기 용이하도록 개발됐다는 것이다.
이걸 굳이 언급하는 것은 gateway api가 서비스 메시의 대체제로도 어느 정도 활용될 수 있기 때문이다.
구체적으로는 서비스 메시를 설정하는 리소스라고 하는 것이 맞겠다.
대표적으로 이스티오의 설정들을 여기의 리소스들을 이용해서 진행하는 것이 가능한데, 실제로 양식을 보면 거의 비슷하게 생긴 것을 볼 수 있다.
(이스티오 팀에서 게이트웨이 api를 주도적으로 개발하고 있어서 그런 것도 있다.)
이렇게 하기 위해서는 gateway api의 하위 프로젝트인 GAMMA Initiative 프로젝트에서 개발 중인 기능을 사용해야 한다.[4]
Gateway Api for Mesh Management and Administration은 2022년부터 생긴 서브 프로젝트로 gateway api를 클러스터 내부의 트래픽을 조절하는데 사용하기 위한 기능 개발 목적을 가지고 있는 작업을 진행하고 있다.
글을 계속 봤을 때는 기본적으로 다른 네임스페이스 간 라우트를 통제하는 것에 주안점을 두고 있는 것으로 보인다.
productor, consumer 라우트를 구분하는 기준이 네임스페이스던데, 아직 문서가 명쾌하게 정리가 이뤄지지 않은 듯한 느낌을 받았다.
실습 진행
이제 본격적으로 gateway api를 활용해 이전 실습을 재현한다.
- 이스티오 세팅
- 샘플 앱 배포
- 외부 접근 세팅
- 에러 내고 에러율 낮추기
기본 세팅 및 샘플 앱 배포
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
profile: demo
components:
ingressGateways:
- name: istio-ingressgateway
enabled: false
egressGateways:
- name: istio-egressgateway
enabled: false
meshConfig:
defaultProviders:
metrics:
- prometheus
tracing: []
게이트웨이 api에 대한 예제는 공식 문서에서 친절하게 제공되고 있다.[5]
일단 게이트웨이의 리소스들을 써야 하니 istio의 ingress gateway도 비활성화시킨 채로 설치한다.
(이 부분이 정말 큰 차이 중 하나)
kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
{ kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.2.1" | kubectl apply -f -; }
그 다음 게이트웨이 crd를 설치해준다.
위 명령어는 이미 crd가 있으면 건너뛰고, 없을 경우에만 공식 레포에서 설치를 진행하는 명령어이다.
요로코롬 설치가 됐다면 성공.
k get gatewayclass
게이트웨이 api에서 인프라 레벨 관리 역할 리소스를 확인해본다.
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: istio
spec:
controllerName: istio.io/gateway-controller
description: The default Istio GatewayClass
GatewayClass는 직접 만들지 않아도 알아서 만들어지는 것을 확인할 수 있다.
istiod는 gateway api crd가 세팅되면 이를 확인하고 알아서 gatewayclass를 만들어준다.
kubectl label namespace default istio-injection=enabled
kubectl apply -f bookinfo.yaml
이건 다시 언급하진 않겠다.
bookinfo 예제를 다시 배포한다.
외부 접근 설정
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
gatewayClassName: istio
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Same
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: bookinfo
spec:
parentRefs:
- name: bookinfo-gateway
rules:
- matches:
- path:
type: Exact
value: /productpage
- path:
type: PathPrefix
value: /static
- path:
type: Exact
value: /login
- path:
type: Exact
value: /logout
- path:
type: PathPrefix
value: /api/v1/products
backendRefs:
- name: productpage
port: 9080
이제 본격적으로 gateway, route 리소스를 만든다.
실질적인 생김새가 istio의 gateway, virtualservice의 양식과 상당히 비슷한 것을 볼 수 있다.
gateway 리소스의 listeners
필드만 잠시 보자면, 이 부분은 어떤 트래픽을 받을지, 그리고 이렇게 열린 게이트웨이에 연결될 수 있는 route 리소스는 어떤 것이 가능한지 지정할 수 있다.
# 모든 네임스페이스의 라우트 허용
allowedRoutes:
namespaces:
from: ALL
---
# 셀렉팅된 네임스페이스만 허용
allowedRoutes:
namespaces:
from: Selector
selector:
kubernetes.io/name: test
allowedRoutes
필드의 경우 어떤 네임스페이스의 route 리소스를 허용할지 지정한다.
기본은 같은 네임스페이스의 리소스만 허용하는데, 위처럼 모든 네임스페이스나 특정 네임스페이스들만 허용하는 것도 가능하다.
성공적으로 두 리소스가 세팅됐다.
gateway 리소스는 인그레스 컨트롤러를 세팅할 때와 마찬가지로 만들어지면 인그레스 트래픽을 담당할 서비스가 만들어지는데, 기본적으로는 로드밸런서 타입으로 만들어진다.
현 실습에서는 로드밸런서 유형을 사용할 수 없으므로 이걸 cluster ip로 바꿔주겠다.
kubectl annotate gateway bookinfo-gateway networking.istio.io/service-type=ClusterIP --namespace=default
gateway에 어노테이션으로 서비스 유형을 지정해준다.
그러면 gateway 리소스가 주소를 할당받고 programmed 상태가 된다.
kubectl port-forward svc/bookinfo-gateway-istio 8080:80
이번에도 배포할 때 바로 노드포트 세팅이 되게 하고 싶었는데, 문서를 찾아봤을 때 이걸 미리 세팅할 수 있는 방법은 없는 것 같았다.
서비스 타입을 노트포트로 세팅을 하는 건 가능한데, 어떤 포트를 사용할지 지정하는 필드가 없다.
아쉬운 대로 그냥 포트포워딩으로 실습을 진행한다.
제대로 들어와진다!
while true; do curl -s http://127.0.0.1:8080/productpage | grep -o "<title>.*</title>" ; sleep 1; done
실시간 트래픽 확인을 위해 이번에도 반복문을 세팅한다.
에러 내는 실습 예제를 그대로 적용해서 에러가 나고 있긴 한데, 아무튼 똑같이 세팅되는 것을 확인할 수 있다.
config 탭에 들어가면 위와 같이 gateway api의 리소스들이 추적되는 것을 확인할 수 있다.
에러율 줄이기
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/experimental-install.yaml
게이트웨이 api에도 재시도 설정 필드가 있긴 한데, 이것은 아직까진 실험적 버전에서만 가능하다.
가능한 이스티오에서 진행한 실습을 전부 진행하고 싶어 추가적으로 실험 버전으로 다시 crd를 수정했다.[6]
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: ratings
spec:
parentRefs:
- name: ratings
kind: Service
group: ""
port: 9080
rules:
- name: retry
matches:
- path:
type: PathPrefix
value: /ratings
retry:
attempts: 5
codes:
- 503
- 501
backendRefs:
- name: ratings
port: 9080
GAMMA 설정 방식 자체는 간단하다.
그냥 parentRefs 필드를 gateway가 아니라 서비스로 지정을 해주면 된다.
그럼 해당 서비스로 들어가는 트래픽에 대해서 매칭되는 트래픽에 대해서 해당 룰이 적용된다고 나와있다.
이렇게 키알리 서비스 탭에서 ratings 서비스를 들어가면 istio config가 설정된 것이 확인된다.
로그를 살펴보면 retry가 이뤄지는 것이 확인된다.
트레이싱을 보면 세팅된 상태에서는 확실하게 재시도되는 것까지 트레이스로 확인된다.
의도한 대로 시각화까지 되는 것을 확인하면 아무튼 성공!
결론
이번 주차는 간단하게 실습을 하는 게 목적이라 상세 분석은 진행하지 않았다(그런 것 치고는 꽤 많이 판 것 같긴 하지만).
다만 gateway api와 기존 이스티오의 리소스를 간단하게 비교하자면..[7]
- 이스티오의 gateway는 이미 배포된 게이트웨이 관련 워크로드를 기반(ingress gatewayr가 그 워크로드이다)으로 세팅만 하는 리소스이다.
- 반면 gateway api의 gateway는 설정과 배포를 동시에 진행하는 리소스이다.
- gatewayclass가 제대로 설정돼있다면, gateway 리소스를 만드는 것만으로 실제 트래픽을 담당하는 워크로드가 같이 배포된 것을 확인할 수 있었다.
- 그래서 ingress gateway를 따로 구축하지 않고도 편하게 설정이 가능하다!
- 이스티오의 virtualservice는 모든 프로토콜을 하나의 리소스에서 관리한다.
- gateway api는 각 프로토콜에 맞게 route 리소스(HTTPRoute, TLSRoute, TCPRoute 등등)를 따로 만든다.
- 아직 gateway api는 이스티오의 모든 기능을 커버하진 않는다!
- 일단 대표적으로 위에서도 보았듯이 gateway api는 서비스 메시로서 기능하기 위한 리소스가 아니라 인그레스를 대체하는 리소스의 집합이다.
- 그래서 서비스 메시를 기대하고 사용하려 하면.. 조금 아쉬운 경우를 왕왕 마주할 것으로 생각된다.
- 당장 재시도 설정을 하기 위해 stable이 아닌 상태의 api를 사용해야 했던 것만 봐도 그렇다.
사용성은 어떠한가?
일단 설정 방식 자체는 대체로 비슷해서 엄청난 차이가 느껴지진 않았다.
다만 이스티오의 리소스는 이스티오 컨트롤 플레인과 잘 결합되어 설정이 잘 되는 편이다.
그러나 게이트웨이 api는 통신 간 암호화를 위해서는 추가적인 설정을 필요로 한다던가 하는 별도의 설정들이 더 필요한 편이다.
게이트웨이 api는 쿠버의 공식 api로 결합되었기에, 서비스 메시를 사용하지 않는 조직에서 인그레스를 대체하기 위한 용도로 사용하기에는 꽤나 유용하다.
인그레스는 앞으로도 업데이트가 되지 않을 예정이기에 궁극적으로 게이트웨이 api를 사용하는 방향으로 가는 것은 기술 부채로부터 상대적으로 안전하다.
앞으로 기능 개발과 문서화가 더 이뤄져서 성숙도가 높아진다면 완전히 서비스 메시 설정 리소스로서 활용하기에도 좋을 것이라 생각한다.
참고로 게이트웨이 api에는 referencegrants라는 리소스가 있다.
이것은 네임스페이스가 리소스 공유를 위한 리소스 세팅으로, 최근 스토리지 관련 새로운 리소스들이 해당 리소스를 활용하여 네임스페이스 간 공유 기능을 제공하고 있다.
앞으로도 gateway api는 활용될 가능성이 무궁무진하다는 것이다!
이전 글, 다음 글
다른 글 보기
이름 | index | noteType | created |
---|---|---|---|
1W - 서비스 메시와 이스티오 | 1 | published | 2025-04-10 |
1W - 간단한 장애 상황 구현 후 대응 실습 | 2 | published | 2025-04-10 |
1W - Gateway API를 활용한 설정 | 3 | published | 2025-04-10 |
1W - 네이티브 사이드카 컨테이너 이용 | 4 | published | 2025-04-10 |
2W - 엔보이 | 5 | published | 2025-04-19 |
2W - 인그레스 게이트웨이 실습 | 6 | published | 2025-04-17 |
3W - 버츄얼 서비스를 활용한 기본 트래픽 관리 | 7 | published | 2025-04-22 |
3W - 트래픽 가중치 - flagger와 argo rollout을 이용한 점진적 배포 | 8 | published | 2025-04-22 |
3W - 트래픽 미러링 패킷 캡쳐 | 9 | published | 2025-04-22 |
3W - 서비스 엔트리와 이그레스 게이트웨이 | 10 | published | 2025-04-22 |
3W - 데스티네이션 룰을 활용한 네트워크 복원력 | 11 | published | 2025-04-26 |
3W - 타임아웃, 재시도를 활용한 네트워크 복원력 | 12 | published | 2025-04-26 |
4W - 이스티오 메트릭 확인 | 13 | published | 2025-05-03 |
4W - 이스티오 메트릭 커스텀, 프로메테우스와 그라파나 | 14 | published | 2025-05-03 |
4W - 오픈텔레메트리 기반 트레이싱 예거 시각화, 키알리 시각화 | 15 | published | 2025-05-03 |
4W - 번외 - 트레이싱용 심플 메시 서버 개발 | 16 | published | 2025-05-03 |
5W - 이스티오 mTLS와 SPIFFE | 17 | published | 2025-05-11 |
5W - 이스티오 JWT 인증 | 18 | published | 2025-05-11 |
5W - 이스티오 인가 정책 설정 | 19 | published | 2025-05-11 |
6W - 이스티오 설정 트러블슈팅 | 20 | published | 2025-05-18 |
6W - 이스티오 컨트롤 플레인 성능 최적화 | 21 | published | 2025-05-18 |
8W - 가상머신 통합하기 | 22 | published | 2025-06-01 |
8W - 엔보이와 iptables 뜯어먹기 | 23 | published | 2025-06-01 |
9W - 앰비언트 모드 구조, 원리 | 24 | published | 2025-06-07 |
9W - 앰비언트 헬름 설치, 각종 리소스 실습 | 25 | published | 2025-06-07 |
7W - 이스티오 메시 스케일링 | 26 | published | 2025-06-09 |
7W - 엔보이 필터를 통한 기능 확장 | 27 | published | 2025-06-09 |
관련 문서
이름 | noteType | created |
---|
참고
https://kubernetes.io/docs/concepts/services-networking/gateway/ ↩︎
https://gateway-api.sigs.k8s.io/reference/spec/#gatewayinfrastructure ↩︎
https://istio.io/latest/docs/setup/getting-started/#gateway-api ↩︎
https://gateway-api.sigs.k8s.io/guides/#install-experimental-channel ↩︎
https://istio.io/latest/docs/tasks/traffic-management/ingress/gateway-api/ ↩︎